#include "aodv.h"
#include "aodv_types.h"
#include "net_interface.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

// 模拟节点结构
typedef struct {
    uint32_t ip;
    // 在实际实现中，这里应该包含AODV协议栈的完整状态
} simulated_node_t;

// 模拟网络拓扑
typedef struct {
    int num_nodes;
    simulated_node_t *nodes;
    // 在实际实现中，这里应该包含节点之间的连接关系
} simulated_network_t;

// 创建模拟节点
simulated_node_t *create_simulated_node(uint32_t ip) {
    simulated_node_t *node = (simulated_node_t *)malloc(sizeof(simulated_node_t));
    if (node != NULL) {
        node->ip = ip;
    }
    return node;
}

// 创建模拟网络
simulated_network_t *create_simulated_network(int num_nodes) {
    simulated_network_t *network = (simulated_network_t *)malloc(sizeof(simulated_network_t));
    if (network != NULL) {
        network->num_nodes = num_nodes;
        network->nodes = (simulated_node_t *)malloc(num_nodes * sizeof(simulated_node_t));
        
        // 为节点分配IP地址（192.168.1.x）
        for (int i = 0; i < num_nodes; i++) {
            network->nodes[i].ip = (192 << 24) | (168 << 16) | (1 << 8) | (i + 1);
        }
    }
    return network;
}

// 释放模拟网络
void free_simulated_network(simulated_network_t *network) {
    if (network != NULL) {
        free(network->nodes);
        free(network);
    }
}

// 模拟节点间通信
void simulate_node_communication(simulated_node_t *sender, simulated_node_t *receiver) {
    printf("\n=== Simulating communication from %d.%d.%d.%d to %d.%d.%d.%d ===\n",
           (sender->ip >> 24) & 0xFF, (sender->ip >> 16) & 0xFF, 
           (sender->ip >> 8) & 0xFF, sender->ip & 0xFF,
           (receiver->ip >> 24) & 0xFF, (receiver->ip >> 16) & 0xFF, 
           (receiver->ip >> 8) & 0xFF, receiver->ip & 0xFF);
    
    // 初始化发送方的AODV协议栈
    aodv_init(sender->ip, NULL);
    
    // 发送测试数据
    char test_data[] = "Hello AODV!";
    aodv_send_data(receiver->ip, test_data, strlen(test_data));
    
    // 模拟时间流逝，处理定时器事件
    for (int i = 0; i < 10; i++) {
        process_timers();
        // 在实际实现中，这里应该模拟网络中其他节点的活动
    }
    
    // 打印路由表和邻居表
    aodv_print_route_table();
    aodv_print_neighbor_table();
    aodv_print_stats();
    
    // 清理资源
    aodv_cleanup();
}

// 模拟简单的网络拓扑
void simulate_simple_topology() {
    printf("\n=== Simulating Simple Network Topology ===\n");
    
    // 创建3个节点的网络
    simulated_network_t *network = create_simulated_network(3);
    if (network == NULL) {
        printf("Failed to create simulated network\n");
        return;
    }
    
    // 打印节点信息
    printf("Created %d nodes:\n", network->num_nodes);
    for (int i = 0; i < network->num_nodes; i++) {
        printf("Node %d: %d.%d.%d.%d\n", i+1,
               (network->nodes[i].ip >> 24) & 0xFF, 
               (network->nodes[i].ip >> 16) & 0xFF, 
               (network->nodes[i].ip >> 8) & 0xFF, 
               network->nodes[i].ip & 0xFF);
    }
    
    // 模拟节点1和节点3之间的通信（需要经过节点2）
    simulate_node_communication(&network->nodes[0], &network->nodes[2]);
    
    // 释放资源
    free_simulated_network(network);
}

// 模拟链路故障
void simulate_link_failure() {
    printf("\n=== Simulating Link Failure ===\n");
    
    // 创建2个节点的网络
    simulated_network_t *network = create_simulated_network(2);
    if (network == NULL) {
        printf("Failed to create simulated network\n");
        return;
    }
    
    // 初始化节点1的AODV协议栈
    aodv_init(network->nodes[0].ip, NULL);
    
    // 模拟链路故障
    printf("Simulating link failure with neighbor %d.%d.%d.%d\n",
           (network->nodes[1].ip >> 24) & 0xFF, 
           (network->nodes[1].ip >> 16) & 0xFF, 
           (network->nodes[1].ip >> 8) & 0xFF, 
           network->nodes[1].ip & 0xFF);
    
    handle_link_failure(network->nodes[1].ip);
    
    // 打印路由表和邻居表
    aodv_print_route_table();
    aodv_print_neighbor_table();
    
    // 清理资源
    aodv_cleanup();
    free_simulated_network(network);
}

// 主函数
int main() {
    printf("=== AODV Routing Protocol Test ===\n\n");
    
    // 模拟简单网络拓扑
    simulate_simple_topology();
    
    // 模拟链路故障
    simulate_link_failure();
    
    printf("\n=== Test Completed ===\n");
    
    return 0;
}